﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using JelloPhysics;
using Microsoft.Xna.Framework;
using System.Drawing.Drawing2D;

namespace PhysicsDemo
{
    public partial class MainForm : Game
    {
        private Brush borderBrush = new SolidBrush(Color.Black);
        private Random rand = new Random();
        // 10个矩形方块
        public List<Body> staticBodies = new List<Body>();
        public World world = new World();
        public List<Polygon> ballList = new List<Polygon>();

        Font font = null;
        Brush blackBrush = null;
        Brush whiteBrush = null;
        Bitmap bmpBuffer = null;

        public MainForm()
        {
            InitializeComponent();
            font = new Font("Simsun", 12);
            blackBrush = new SolidBrush(Color.Black);
            whiteBrush = new SolidBrush(Color.White);
            bmpBuffer = new Bitmap(
                Screen.PrimaryScreen.WorkingArea.Width, 
                Screen.PrimaryScreen.WorkingArea.Height);

            this.FPS = 360;
        }

        private void CreatePlatforms()
        {
            foreach (Body body in this.staticBodies)
            {
                this.world.removeBody(body);
            }
            staticBodies.Clear();
            double num = this.ClientSize.Height / 10.0;
            double num2 = num / 2.0;
            for (int i = 0; i < 9; i++)
            {
                float x = (float)(3.0 + (this.rand.NextDouble() * 10.0));
                // 添加10个矩形方块
                ClosedShape shape = new ClosedShape();
                shape.begin();
                shape.addVertex(new Vector2(-x, -1f));
                shape.addVertex(new Vector2(-x, 1f));
                shape.addVertex(new Vector2(x, 1f));
                shape.addVertex(new Vector2(x, -1f));
                shape.finish();
                Body item = new Body(
                    this.world, shape, float.PositiveInfinity,
                    new Vector2((float)((this.rand.NextDouble() * num) - num2),
                    (float)((((this.rand.NextDouble() * num) * 0.75) - num2) - 5.0)),
                    (float)(((this.rand.NextDouble() * 3.1415926535897931) / 8.0) - 0.19634954084936207),
                    Vector2.One, false);

                this.staticBodies.Add(item);
            }
        }

        private void DropBalloon()
        {
            // 添加1个球
            ClosedShape s = new ClosedShape();

            s.begin();
            for (double i = 0.0; i < 6.2831853071795862; i += 0.31415926535897931)
            {
                s.addVertex(new Vector2((float)Math.Sin(i), (float)Math.Cos(i)));
            }
            s.finish();

            double num2 = this.ClientSize.Height / 50.0;
            float num3 = (float)(1.0 + (2.0 * this.rand.NextDouble()));

            FallingBody body = new FallingBody(
                this.world, 
                s, 
                1f, 
                40f, 
                100f, 
                10f, 
                100f, 
                10f,
                new Vector2((float)((this.rand.NextDouble() * num2) - (num2 / 2.0)), 20f),
                MathHelper.ToRadians((float)new Random().Next(360)), 
                new Vector2(num3));

            int count = s.Vertices.Count;
            for (int j = 0; j < count; j++)
            {
                body.addInternalSpring(j, (j + 4) % count, 400f, 12f);
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
        }

        private void MainForm_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DropBalloon();
            }
            else if (e.Button == MouseButtons.Right)
            {
                CreatePlatforms();
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //base.OnPaintBackground(e);
        }

        protected override void Draw(GameTime gameTime)
        {
            //base.OnPaint(e);

            Graphics g = Graphics.FromImage(bmpBuffer);
            g.Clear(Color.White);

            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.High;
            g.SmoothingMode = SmoothingMode.HighQuality;

            string strFPS = string.Format(" fps: {0} ", this.RealFPS);
            if (gameTime.IsRunningSlowly)
            {
                strFPS = strFPS + " IsRunningSlowly";
            }
            g.DrawString(strFPS, font, blackBrush, 10, 10);

            foreach (Body body in staticBodies)
            {
                Polygon poly = body.ObjectTag as Polygon;
                if (poly != null)
                {
                    List<Point> points = poly.Points;
                    if (points.Count == 4)
                    {
                        Pen p = new Pen(poly.Stroke, poly.StrokeThickness);
                        GraphicsPath path = new GraphicsPath();
                        Point[] pos = new Point[points.Count];
                        for (int n = 0; n < points.Count; n++)
                        {
                            pos[n] = points[n];
                        }
                        path.AddPolygon(pos);
                        g.DrawPath(p, path);
                        g.FillPath(poly.Fill, path);
                    }
                }
            }
            foreach (Polygon objectTag in ballList)
            {
                List<Point> points = objectTag.Points;
                if (points.Count > 4)
                {
                    Pen p = new Pen(objectTag.Stroke, objectTag.StrokeThickness);
                    GraphicsPath path = new GraphicsPath();
                    Point[] pos = new Point[points.Count];
                    for (int n = 0; n < points.Count; n++)
                    {
                        pos[n] = points[n];
                    }
                    path.AddPolygon(pos);
                    g.DrawPath(p, path);
                    g.FillPath(objectTag.Fill, path);
                }
            }

            g = Graphics.FromHwnd(this.Handle);
            g.DrawImage(bmpBuffer, 0, 0);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (this.staticBodies.Count == 0)
            {
                // 添加矩形方块
                this.CreatePlatforms();
            }
            for (int i = 0; i < 2; i++)
            {
                //this.world.update(0.008333334f);
                // 变形比例？
                this.world.update((float)gameTime.ElapsedGameTime.TotalSeconds);
            }
            // 记录旧的数据，重新计算球的数据
            List<Body> list = new List<Body>();
            double actualWidth = this.ClientSize.Width;
            double actualHeight = this.ClientSize.Height;
            // 循环查找
            foreach (Body body in this.world)
            {
                // 把球拿出来重新计算位置和形状
                Polygon objectTag = body.ObjectTag as Polygon;
                if (objectTag == null)
                {
                    objectTag = new Polygon();
                    objectTag.Fill = new SolidBrush(
                        Color.FromArgb(50,
                        (byte)this.rand.Next(0xff),
                        (byte)this.rand.Next(0xff),
                        (byte)this.rand.Next(0xff)));
                    objectTag.StrokeThickness = 2.0f;
                    objectTag.Stroke = this.borderBrush;
                    ballList.Add(objectTag);
                    body.ObjectTag = objectTag;
                }
                List<Point> points = new List<Point>();
                bool flag = false;
                double num4 = actualHeight / 50.0;
                // 边界点集
                foreach (PointMass mass in body)
                {
                    double x = (actualWidth / 2.0) + (mass.Position.X * num4);
                    double y = (actualHeight / 2.0) - (mass.Position.Y * num4);
                    if (((x >= 0.0) && (x < actualWidth)) && ((y >= 0.0) && (y < actualHeight)))
                    {
                        // 已经移动到窗口之外
                        flag = true;
                    }
                    points.Add(new Point((int)x, (int)y));
                }
                // 边界点集
                objectTag.Points = points;
                if (!flag)
                {
                    list.Add(body);
                }
            }
            foreach (Body body2 in list)
            {
                // 删除已经移动到窗口之外的物体
                this.world.removeBody(body2);
                ballList.Remove(body2.ObjectTag as Polygon);
            }
        }


    }
}
